package com.hepinghospital.user.ui.xylink

import android.Manifest
import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.log.L
import android.os.Handler
import android.os.IBinder
import android.view.View
import com.ainemo.module.call.data.Enums
import com.ainemo.module.call.data.RemoteUri
import com.ainemo.sdk.otf.NemoSDK
import com.ainemo.sdk.otf.NemoSDKListener
import com.ainemo.sdk.otf.SimpleNemoSDkListener
import com.ainemo.sdk.otf.VideoInfo

import com.hepinghospital.user.R
import com.hepinghospital.user.base.BaseActivity
import com.hepinghospital.user.ui.xylink.view.VideoCell
import com.hepinghospital.user.util.CommonTime
import com.hepinghospital.user.util.ToastUtil
import com.tbruyelle.rxpermissions2.RxPermissions
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_call_video.*
import kotlinx.android.synthetic.main.media_main_btn.*
import kotlinx.android.synthetic.main.view_call_detail.*
import java.util.concurrent.TimeUnit

/**
 * @Description: 视频聊天界面
 * @Author: lzp
 * @CreateDate: 2021/12/31 11:19
 * @UpdateRemark: 更新说明
 */
class XyCallActivity : BaseActivity(), VideoFragment.VideoCallback {
    private var isVideoMute: Boolean = false
    private var isMuteMic: Boolean = false
    private var defaultCameraFront = true

    //    private lateinit var outgoingNumber: String
    private var inviteCallIndex: Int = -1

    private var localVideoInfo: VideoInfo? = null
//    private var fullVideoInfo: VideoInfo? = null

    private lateinit var videoFragment: SpeakerVideoFragment
    private lateinit var compositeDisposable: CompositeDisposable

    private var isToolbarShowing = false // toolbar隐藏标记
    private val sDefaultTimeout = 5000

    private var isCallStart = false

    private val handler = Handler()


    @kotlin.annotation.Retention(AnnotationRetention.SOURCE)
    annotation class VideoStatus {
        companion object {
            var VIDEO_STATUS_NORMAL = 0
            var VIDEO_STATUS_LOW_AS_LOCAL_BW = 1
            var VIDEO_STATUS_LOW_AS_LOCAL_HARDWARE = 2
            var VIDEO_STATUS_LOW_AS_REMOTE = 3
            var VIDEO_STATUS_NETWORK_ERROR = 4
            var VIDEO_STATUS_LOCAL_WIFI_ISSUE = 5
        }
    }

    override fun onStart() {
        super.onStart()
        defaultCameraFront = NemoSDK.defaultCameraId() == 1
        NemoSDK.getInstance().releaseCamera()
        NemoSDK.getInstance().requestCamera()
    }

    override fun getLayoutResource(): Int {
        return R.layout.activity_call_video
    }

    override fun initData() {
        val backgroundCallService = Intent(this, BackgroundCallService::class.java)
        bindService(backgroundCallService, xyCallConnection, BIND_AUTO_CREATE)
        videoFragment = SpeakerVideoFragment()
        videoFragment.setVideoCallback(this)
        supportFragmentManager.beginTransaction().add(R.id.fl_video, videoFragment).commitAllowingStateLoss()
        //  来电
//        outgoingNumber = intent.getStringExtra("name")
        inviteCallIndex = intent.getIntExtra("callIndex", -1)
        showCallIncoming(intent.getStringExtra("name") ?: "")
//        showCallOutGoing(outgoingNumber)
    }

//    override fun setStatusBar() {
//        StatusBarUtil.setTransparent(this)
//    }

    override fun initViews() {
//        val win = window
//        win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)
//        win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
        compositeDisposable = CompositeDisposable()
        initListener()
        checkPermission()
//        hideOrShowToolbar(isToolbarShowing)
        setVideoState(false)
    }

    private fun initListener() {
        NemoSDK.getInstance().setNemoSDKListener(object : SimpleNemoSDkListener() {
            override fun onCallStateChange(state: NemoSDKListener.CallState?, reason: String?) {
                when (state) {
                    NemoSDKListener.CallState.CONNECTING -> {
                    }
                    NemoSDKListener.CallState.DISCONNECTED -> {
//                        ToastUtil.showToastOnUIThread(this@XyCallActivity, "Call disconnected reason: $reason")
                        finish()
                    }
                    NemoSDKListener.CallState.CONNECTED -> {
                        Observable.just(0).observeOn(AndroidSchedulers.mainThread())
                                .subscribe { showCallConnected() }
                    }
                }
            }

            override fun onVideoStatusChange(videoStatus: Int) {
                when (videoStatus) {
                    VideoStatus.VIDEO_STATUS_NORMAL -> {
                        ToastUtil.showToastOnUIThread(this@XyCallActivity, "网络正常")
                    }
                    VideoStatus.VIDEO_STATUS_LOW_AS_LOCAL_BW -> {
                        ToastUtil.showToastOnUIThread(this@XyCallActivity, "本地网络不稳定")
                    }
                    VideoStatus.VIDEO_STATUS_LOW_AS_LOCAL_HARDWARE -> {
                        ToastUtil.showToastOnUIThread(this@XyCallActivity, "系统忙，视频质量降低")
                    }
                    VideoStatus.VIDEO_STATUS_LOW_AS_REMOTE -> {
                        ToastUtil.showToastOnUIThread(this@XyCallActivity, "对方网络不稳定")
                    }
                    VideoStatus.VIDEO_STATUS_NETWORK_ERROR -> {
                        ToastUtil.showToastOnUIThread(this@XyCallActivity, "网络不稳定，请稍候")
                    }
                    VideoStatus.VIDEO_STATUS_LOCAL_WIFI_ISSUE -> {
                        ToastUtil.showToastOnUIThread(this@XyCallActivity, "WiFi信号不稳定")
                    }
                }
            }

            @SuppressLint("CheckResult")
            override fun onVideoDataSourceChange(videoInfos: MutableList<VideoInfo>, hasVideoContent: Boolean) {
                Observable.just(0).observeOn(AndroidSchedulers.mainThread()).subscribe { videoFragment.setRemoteVideoInfo(videoInfos, hasVideoContent) }
            }
        })

        hang_up.setOnClickListener {
            NemoSDK.getInstance().hangup()
            NemoSDK.getInstance().releaseLayout()
            NemoSDK.getInstance().releaseCamera()
            finish()
        }
        media_switch.setOnClickListener {
            isVideoMute = !isVideoMute
            setVideoState(isVideoMute)
        }
        mic_mute.setOnClickListener {
            this.isMuteMic = !isMuteMic
            enableMic(isMuteMic, false)
        }

        media_camera.setOnClickListener {
            defaultCameraFront = !defaultCameraFront
            NemoSDK.getInstance().switchCamera(if (defaultCameraFront) 0 else 1) // 0：后置 1：前置
        }

        bt_call_drop.setOnClickListener {
//            NemoSDK.getInstance().hangup()
            NemoSDK.getInstance().answerCall(inviteCallIndex, false)
            NemoSDK.getInstance().releaseLayout()
            NemoSDK.getInstance().releaseCamera()
            finish()
        }

        bt_call_accept.setOnClickListener {
            NemoSDK.getInstance().answerCall(inviteCallIndex, true)
        }
    }

    // remember to release resource when destroy
    override fun onDestroy() {
        if (!compositeDisposable.isDisposed) {
            compositeDisposable.dispose()
        }
        videoFragment.onDestroy()
//        orientationEventListener.disable()
//        mVolumeManager.onDestory()
//        val fragments: List<VideoFragment> = videoPagerAdapter.getFragments()
//        for (videoFragment in fragments) {
//            videoFragment.onDestroy()
//        }
        unbindService(xyCallConnection)
        super.onDestroy()
    }

    //来电
    private fun showCallIncoming(callName: String = "医生") {
        view_call_detail.visibility = View.VISIBLE
        tv_call_tips.text = "邀请您视频通话......"
        tv_call_name.text = callName
    }


    // 通话时长
    private fun initCallDuration() {
        if (!compositeDisposable.isDisposed) {
            compositeDisposable.clear()
        }
        compositeDisposable.add(Observable.interval(1, TimeUnit.SECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { aLong: Long -> network_state_timer.text = CommonTime.formatTime(aLong) })
    }

    /**
     * 通话接听, 计时 显示toolbar等
     */
    private fun showCallConnected() {
        NemoSDK.getInstance().setLayoutBuilder(SpeakerLayoutBuilder())
        isCallStart = true
        view_call_detail.visibility = View.GONE
        initCallDuration()
        showToolbar(sDefaultTimeout)
        videoFragment.setLocalVideoInfo(buildLocalLayoutInfo())
        NemoSDK.getInstance().setVideoMute(isVideoMute)
        NemoSDK.getInstance().enableMic(isMuteMic, false)
    }

    private fun buildLocalLayoutInfo(): VideoInfo {
        val li = VideoInfo()
        li.layoutVideoState = Enums.LAYOUT_STATE_RECEIVED
        li.dataSourceID = NemoSDK.getLocalVideoStreamID()
        li.videoMuteReason = Enums.MUTE_BY_USER
        li.remoteName = NemoSDK.getInstance().userName
        li.participantId = NemoSDK.getInstance().userId.toInt()
        li.remoteID = RemoteUri.generateUri(NemoSDK.getInstance().userId.toString(), Enums.DEVICE_TYPE_SOFT)
        localVideoInfo = li
        return li
    }


    /**
     * 打开、关闭本地摄像头，同时也会操作Camera
     *
     * @param isMuteVideo true 关闭摄像头，false 打开摄像头
     */
    private fun setVideoState(videoMute: Boolean) {
        if (videoMute) {
            media_switch.setImageResource(R.mipmap.icon_video_open)
            tv_close_video.text = resources.getString(R.string.open_video)
        } else {
            media_switch.setImageResource(R.mipmap.icon_video_close)
            tv_close_video.text = resources.getString(R.string.close_video)
        }
        NemoSDK.getInstance().setVideoMute(isVideoMute)
    }

    /**
     * 关闭、打开本地麦克风
     *
     * @param isMuteMic true 关闭麦克风，false 打开麦克风
     * @param notifyRemote true 通知远端，false 不通知远端。非强制静音模式时需通知远端，强制静音模式无需通知远端。远端指会里的其他终端
     */
    private fun enableMic(isMuteMic: Boolean, notifyRemote: Boolean = false) {
        if (isMuteMic) {
            mic_mute.setImageResource(R.mipmap.icon_voice_mute)
        } else {
            mic_mute.setImageResource(R.mipmap.icon_voice_unmute)
        }
        NemoSDK.getInstance().enableMic(isMuteMic, false)
    }

    private val xyCallConnection: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName, service: IBinder) {}
        override fun onServiceDisconnected(name: ComponentName) {}
    }

    @SuppressLint("CheckResult")
    private fun checkPermission() {
        val permissions = RxPermissions(this)
        permissions.request(Manifest.permission.RECORD_AUDIO)
                .subscribe { hasMicPermission: Boolean ->
                    L.i("AAA", "audio permission: " + hasMicPermission +
                            ", mic state: " + NemoSDK.getInstance().isMicMuted)
                    if (hasMicPermission) {
                        NemoSDK.getInstance().requestAudioMic()
                    }
                }
    }

    private fun hideOrShowToolbar(show: Boolean) {
        if (show) {
            hideToolbar()
        } else {
            showToolbar(sDefaultTimeout)
        }
    }

    private fun hideToolbar() {
        layout_toolbar.visibility = View.GONE
        isToolbarShowing = false
    }

    private fun showToolbar(timeout: Int) {
        if (!isToolbarShowing) { // show toolbar
            layout_toolbar.visibility = View.VISIBLE
            isToolbarShowing = true
        }
        if (timeout != 0) {
            handler.removeCallbacks(mFadeOut)
            handler.postDelayed(mFadeOut, timeout.toLong())
        }
    }

    private val mFadeOut = Runnable { hideToolbar() }


    override fun onVideoCellSingleTapConfirmed(cell: VideoCell?): Boolean {
//        isToolbarShowing = !isToolbarShowing
        hideOrShowToolbar(isToolbarShowing)
        return false
    }

    override fun onVideoCellDoubleTap(cell: VideoCell?): Boolean {
        return false
    }

    override fun onLockLayoutChanged(pid: Int) {
        updateLockLayout()
    }

    private fun updateLockLayout() {
//        val pid: Int = videoFragment.lockedPid
//        if (pid != 0) {
//            llLockPeople.setVisibility(if (shareState === ShareState.WHITEBOARD) View.GONE else View.VISIBLE)
//        } else {
//            llLockPeople.setVisibility(View.GONE)
//        }
    }

    override fun onFullScreenChanged(cell: VideoCell?) {
//        fullVideoInfo = cell?.layoutInfo
//        updateFeccStatus()
//        checkUiState()
    }

    override fun onContentChanged(lastPid: Long, nowPid: Long) {
    }

    override fun onVideoCellGroupClicked(group: View?) {
    }
}